home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / ee1091.zip / EE.C < prev    next >
Text File  |  1991-10-11  |  22KB  |  1,077 lines

  1. /* ee.c, Yijun Ding, Copyright 1991
  2.  
  3. Compile with TC: tcc ee.c
  4. Compile in unix: gcc ee.c -lcursesX
  5.  
  6. Prototype are listed in the order defined. They are essentially grouped
  7. as cursor move, screen, search, files, misc, mainloop, main.
  8.  
  9. */
  10. #include <stdio.h>
  11. #include <string.h>
  12.  
  13. #define EOL '\0'    /* end of line marker */
  14. #define BLK ' '     /* blank */
  15. #define LF  '\n'    /* new line */
  16. #define NLEN  80    /* buffer line for file name */
  17. #define LMAX  10000 /* max line length */
  18. #define XINC  20    /* increament of x */
  19. #define HLP 28
  20.  
  21. #define CHG 0
  22. #define FIL 1   /* fill */
  23. #define OVR 2   /* insert */
  24. #define CAS 3   /* case sensative */
  25. #define TAB 4   /* tab */
  26. #define POS 5   /* show pos */
  27. #define ALT 6   /* meta_key */
  28. #define SHW 7   /* screen */
  29. #define NEW 8   /* new file */
  30. #define EDT 9   /* quit edit */
  31. #define WIN 10  /* window */
  32. #define NTS 11  /* note posted */
  33. #define ALL 12  /* last flag, quit */
  34. char  flag[ALL+1];
  35. char  fsym[]="|foctp~";
  36.  
  37. typedef struct {
  38.   char name[NLEN];
  39.   int  jump;
  40. } MWIN;          /* my window structure */
  41.  
  42. /* order of \n\r is important for curses */
  43. #define HELP_STR "\n\
  44. Usage: ee [-+line(def=1) -ttab(def=2) file(def=Notes)]\n\r\
  45. \n\
  46. A set mark, append file;    B format, right margin;\n\r\
  47. C shell, execute line;      D cursor right, line end;\n\r\
  48. E cursor up, file top;      F forward search, backward search;\n\r\
  49. G goto line, goto column;   H delete before, delete under;\n\r\
  50. I tab, tab insert;          J play macro, record;\n\r\
  51. K block copy, block cut;    L refresh screen, status;\n\r\
  52. M return;                   N toggle insert mode;\n\r\
  53. O toggle mode;              P command prefix;\n\r\
  54. Q command prefix;           R replace, replace all;\n\r\
  55. S cursor left, line begin;  T delete word, del eol;\n\r\
  56. U block paste, block write; V page down, page up;\n\r\
  57. W window, window cancel;    X cursor down, file bottom;\n\r\
  58. Y block delete line;        Z exit, edit other file;\n\r\
  59. \n\
  60. Each letter represent a control key. Each key corresponds one or two\n\r\
  61. editing commands (seperated by comma). Press the control key for the\n\r\
  62. first editing function, or control-P and the control key for the second\n\r\
  63. editing function.\n\n\r\
  64. Press any key to continue ..."
  65.  
  66. #ifdef __TURBOC__
  67. #define AMAX  0xD000  /* main buffer size */
  68. #define BMAX  0x400   /* block size */
  69. #define YTOP  1
  70.  
  71. #define ttopen()    sww=76;swhfull=23
  72. /* #define highvideo() textattr(0x30)
  73. #define lowvideo()  textattr(0x1F)
  74. #define ttclose()   textattr(0x07) */
  75. #define ttclose()   normvideo()
  76.  
  77. /* honest get a key */
  78. int get_key()
  79. {
  80.   static  char k1[]="GHIKMOPQRS";
  81.   static  char k2[]="sEvSDdXVNh";
  82.   int  key;
  83.   char *s;
  84.  
  85.   if((key=getch()) == 0) {
  86.     if((s=strchr(k1, getch())) == 0)
  87.       return HLP;
  88.     if((key = k2[s-k1]) > 'a')
  89.       flag[ALT]++;
  90.     return key&0x1F;
  91.   }
  92.   return key;
  93. }
  94. #else
  95. #include "eeibm.c"
  96. #endif
  97.  
  98. char  bbuf[10];               /* backup file name */
  99. char  sbuf[NLEN], rbuf[NLEN]; /* search buffer, replace buffer */
  100. char  *ae, aa[AMAX];          /* main buffer */
  101. char  bb[BMAX], *mk;          /* block buffer, mark */
  102. unsigned blen;
  103. char  *dp, *ewb;              /* current pos, line */
  104.  
  105. int xtru, ytru;               /* file position */
  106. int ytot;                     /* 0 <= ytru <= ytot */
  107.  
  108. int swhfull;                  /* screen physical height */
  109. int x, sww;                   /* screen position 1 <= x <= sww */
  110. int y, swh;                   /* screen size 0 <= y <= swh */
  111. int y1, y2;                   /* 1st, 2nd line of window */
  112. int tabsize=8;                /* tab size */
  113.  
  114. FILE  *fi, *fo;
  115. MWIN  win, winnext, wincopy;  /* current, next, other windows */
  116.  
  117. void cursor_up(), cursor_down(), cursor_left(), cursor_right();
  118. void show_rest(int len, char *s);
  119. void show_scr(int fr, int to);
  120. void show_sup(int line), show_sdn(int line);
  121. void show_flag(int x, int g);
  122. void show_note(char *prp);
  123. int  show_gets(char *prp, char *buf);
  124. void show_top(), show_help(), show_mode(), show_status();
  125. void file_read();
  126. char *file_ltab(char *s);
  127. int  file_write(FILE *fp, char *s, char *e);
  128. int  file_fout();
  129. void file_save(int f_all, int f_win);
  130. void file_more();
  131. void file_rs(char *s, char *d);
  132. void goto_x(int xx), goto_y(int yy);
  133. void goto_ptr(char *s);
  134. void goto_row(), goto_col();
  135. int  str_cmp(char *s);
  136. char *goto_find(char *s, int  back);
  137. void goto_search(int back);
  138. void goto_replace(int whole);
  139. void window_other(), window_cancel(), window_size();
  140. void block_put(), block_get(), block_mark();
  141. void block_copy(int delete);
  142. void block_paste(), block_write(), block_line();
  143. int  block_fill();
  144. void block_format();
  145. void key_return(), key_deleol(char *s), key_delete();
  146. void key_backspace(), key_delword(int eol);
  147. void key_tab(int tabi);
  148. void key_normal(int key);
  149. void key_shell(int line);
  150. void key_macros(int record);
  151. void main_meta(int key), main_exec(int key);
  152. void main_loop(), main(int argc, char **argv);
  153.  
  154. /* cursor movement ----------------------------------------- */
  155. void cursor_up()
  156. {
  157.   if(ytru == 0) return;
  158.   ytru--;
  159.   while(*--ewb != EOL) ;
  160.   y--;
  161. }
  162.  
  163. void cursor_down()
  164. {
  165.   if(ytru == ytot) return;
  166.   ytru++;
  167.   while(*++ewb != EOL) ;
  168.   y++;
  169. }
  170.  
  171. /* cursor left & right: x, xtru */
  172. void cursor_left()
  173. {
  174.   if(xtru == 1) return;
  175.   xtru--;
  176.   if(--x < 1) {
  177.     x += XINC;
  178.     flag[SHW]++;
  179.   }
  180. }
  181.  
  182. void cursor_right()
  183. {
  184.   if(xtru == LMAX) return;
  185.   xtru++;
  186.   if(++x > sww) {
  187.     x -= XINC;
  188.     flag[SHW]++;
  189.   }
  190. }
  191.  
  192. #define cursor_pageup() {int i; for(i=1; i<swh; ++i) cursor_up();}
  193. #define cursor_pagedown(){int i; for(i=1; i<swh; ++i) cursor_down();}
  194.  
  195. /* dispaly --------------------------------------------------------*/
  196. /* assuming cursor in correct position: show_rest(sww-x,ewb+xtru) */
  197. void show_rest(len, s)
  198. int  len;
  199. char *s;
  200. {
  201.   char save;
  202.   save = s[len];
  203.   s[len] = 0;
  204.   cputs(s);
  205.   s[len] = save;
  206.   clreol();
  207. }
  208.  
  209. /* ewb and y correct */
  210. void show_scr(fr,to)
  211. int fr, to;
  212. {
  213.   char *s=ewb;
  214.   int  len=sww-1, i=fr;
  215.   unsigned xl=xtru-x;
  216.  
  217.   /* calculate s */
  218.   for(; i<y; i++) while(*--s != EOL) ;
  219.   for(; i>y; i--) while(*++s != EOL) ;
  220.  
  221.   /* first line */
  222.   s++;
  223.   do {
  224.     gotoxy(1, fr+y2);
  225.     if(s<ae && strlen(s) > xl) show_rest(len, s+xl);
  226.     else clreol();
  227.     while(*s++) ;
  228.   } while(++fr <= to);
  229. }
  230.  
  231. void show_sup(line)
  232. int line;
  233. {
  234.   gotoxy(1, y2+line);
  235.   delline();
  236.   show_scr(swh, swh);
  237. }
  238.  
  239. void show_sdn(line)
  240. int line;
  241. {
  242.   gotoxy(1, y2+line);
  243.   insline();
  244.   show_scr(line, line);
  245. }
  246.  
  247. void show_flag(x, g)
  248. int x, g;
  249. {
  250.   gotoxy(14+x, y1);
  251.   putch(g? fsym[x]: '.');
  252.   flag[x] = g;
  253. }
  254.  
  255. void show_note(prp)
  256. char *prp;
  257. {
  258.   gotoxy(17+ALT, y1);
  259.   cputs(prp);
  260.   clreol();
  261.   flag[NTS]++;
  262. }
  263.  
  264. int show_gets(prp, buf)
  265. char *prp, *buf;
  266. {
  267.   int key;
  268.   int col=(-1);
  269.   show_note(prp);
  270.   cputs(": ");
  271.   cputs(buf);
  272.   for(;;) {
  273.     key = get_key();
  274.     if(key >= BLK) {
  275.       if(col < 0) {
  276.         col++;
  277.         show_note(prp);
  278.         cputs(": ");
  279.       }
  280.       buf[col++] = key;
  281.     }
  282.     else if(key == 8) {
  283.       if(col < 0) col = strlen(buf);
  284.       if(col == 0) continue;
  285.       col--;
  286.     }
  287.     else break;
  288.     putch(key);
  289.   }
  290.   flag[ALT] = 0;
  291.   if(col > 0) buf[col] = 0;
  292.   return (key == 27 || *buf == 0);
  293. }
  294.  
  295. void show_top()
  296. {
  297.   int i;
  298.   gotoxy(1, y1);
  299.   highvideo();
  300.   cputs(win.name);
  301.   lowvideo();
  302.   clreol();
  303.   for(i=0; i<=ALT; i++)
  304.     show_flag(i, flag[i]);
  305.   flag[NTS]++;
  306. }
  307.  
  308. void show_help()
  309. {
  310.   clrscr();
  311.   cputs(HELP_STR);
  312.   get_key();
  313.   show_top();
  314.   flag[SHW]++;
  315. }
  316.  
  317. void show_mode()
  318. {
  319.   char *d;
  320.   int  k;
  321.   show_note(fsym);
  322.   putch(BLK);
  323.   k = get_key()|0x60;
  324.   if((d=strchr(fsym, k)) != 0) {
  325.     k = d-fsym;
  326.     show_flag(k, !flag[k]);
  327.   }
  328. }
  329.  
  330. void show_status()
  331. {
  332.   char tbuf[80];
  333.   sprintf(tbuf, "line %d/%d, col %d, char %u/%u/%u+%u",
  334.     ytru+1, ytot, xtru, dp-aa, ae-aa, BMAX, AMAX);
  335.   show_note(tbuf);
  336.   sleep(1);
  337. }
  338.  
  339. /* file operation ---*/
  340. void file_read()
  341. {
  342.   int  c;
  343.   char *col;
  344.   ewb = aa;
  345.   ae = mk = col = aa+1;
  346.   xtru = x = 1;
  347.   ytru = y = ytot = 0;
  348.   if(fi == 0) return;
  349.  
  350.   /* read complete line */
  351.   do {
  352.     c = fgetc(fi);
  353.     if(c == EOF) {
  354.       fclose(fi);
  355.       fi = 0;   /* no more read */
  356.       break;
  357.     }
  358.     if(c == 9) {    /* tab */
  359.       if(flag[TAB] == 0) show_flag(TAB, 1);
  360.       do (*ae++ = BLK);
  361.       while( ((ae-col) % tabsize) != 0);
  362.     }
  363.     else if(c == LF) {
  364.       *ae++ = EOL;
  365.       col = ae;
  366.       ytot++;
  367.     }
  368.     else *ae++ = c;
  369.   } while(ae < aa+AMAX-BMAX || c != LF);
  370.   for(; win.jump>1; win.jump--) cursor_down();
  371. }
  372.  
  373. /* compress one line from end */
  374. char *file_ltab(s)
  375. char *s;
  376. {
  377.   char *d, *e;
  378.   e = d = strchr(s--, EOL);
  379.   while(*--e == BLK) ;  /* trailing blank */
  380.   while(e > s) {
  381.     if(e[0] == BLK && (e-s)%tabsize == 0 && e[-1] == BLK) {
  382.       *--d = 9;
  383.       while(*--e == BLK && (e-s)%tabsize != 0) ;
  384.     }
  385.     else *--d = *e--;
  386.   }
  387.   return d;
  388. }
  389.  
  390. /* routine used for write block file also, this makes it more complicated */
  391. int file_write(fp, s, e)
  392. FILE *fp;
  393. char *s, *e;
  394. {
  395.   if(fp == 0) return 1; /* no write */
  396.   do {
  397.     if(flag[TAB] && *s != EOL) s = file_ltab(s);
  398.     /* if s="", TC return 0, TC++ return -1 */
  399.     if(*s && fputs(s, fp) <= 0) return 1;
  400.     fputc(LF, fp);
  401.     while(*s++ != EOL) ;
  402.   } while(s < e);
  403.   return 0;
  404. }
  405.  
  406. int file_fout()
  407. {
  408.   if(fo == 0) {
  409.     strcpy(bbuf, "YEXXXXXX");
  410.     if(win.name[1] == ':') memcpy(bbuf, win.name, 2);
  411.     fo=fopen((char *)mktemp(bbuf), "w");
  412.   }
  413.   return file_write(fo, aa+1, ae);
  414. }
  415.  
  416. void file_save(f_all, f_win)
  417. int f_all, f_win;
  418. {
  419.   int k='n';
  420.   /* flag[CHG] = 0;  DEBUG*/
  421.   if(flag[CHG] )
  422.   do {
  423.     show_note("Save file (yes/no/cancel): ");
  424.     k = tolower(get_key());
  425.     if(k == 'c') return;
  426.   } while(k != 'y' && k != 'n');
  427.   flag[CHG] = 0;
  428.   flag[EDT]++;
  429.   flag[ALL] = f_all;
  430.   flag[WIN] = f_win;
  431.   if(k == 'n') {
  432.     if(fo ) {
  433.       fclose(fo);
  434.       unlink(bbuf);
  435.       fo = 0;
  436.     }
  437.     return;
  438.   }
  439.   if(file_fout() ) return; /* no write */
  440.   while(fi != 0 ) {
  441.     file_read();
  442.     file_fout();
  443.   }
  444.   fclose(fo);
  445. #if !VMS
  446.   if(flag[NEW] == 0) unlink(win.name);
  447. #endif
  448.   rename(bbuf, win.name);
  449.   fo = 0;
  450. }
  451.  
  452. void file_more()
  453. {
  454.   if(fi != 0) {
  455.     file_fout();
  456.     file_read();
  457.     flag[SHW]++;
  458.   }
  459. }
  460.  
  461. void file_rs(s, d)
  462. char  *d, *s;
  463. {
  464.   char  *e = ae;
  465.   unsigned i = e-s;
  466.  
  467.   /* immediate problem only when block buffer on disk too big */
  468.   if((ae += (d-s)) >= aa+AMAX) {
  469.     show_note("Main buffer full");
  470.     return;
  471.   }
  472.   if(s < d) { /* expand */
  473.     d += e - s;
  474.     s = e;
  475.     while(i-- > 0) *--d = *--s;
  476.     /* while(j-- > 0) if((*--d = *--str) == EOL) ytot++; */
  477.   }
  478.   else {
  479.     /* adjust ytot when shrink */
  480.     for(e=d; e<s; e++) if(*e == EOL) ytot--;
  481.     while(i-- > 0) *d++ = *s++;
  482.   }
  483.   *ae = EOL;  /* last line may not complete */
  484.   if(!flag[CHG] ) {
  485.     show_flag(CHG, 1);
  486.     gotoxy(x, y+y2);
  487.   }
  488. }
  489.  
  490. /* search and goto */
  491. /* xx >= 1, yy >= 0 */
  492. void goto_x(xx)
  493. int  xx;
  494. {
  495.   int i, n;
  496.   n = xtru;
  497.   for(i=xx; i<n; i++) cursor_left();
  498.   for(i=n; i<xx; i++) cursor_right();
  499. }
  500.  
  501. void goto_y(yy)
  502. int  yy;
  503. {
  504.   int i, n;
  505.   n = ytru;
  506.   for(i=yy; i<n; i++) cursor_up();
  507.   for(i=n; i<yy; i++) cursor_down();
  508. }
  509.  
  510. void goto_ptr(s)
  511. char *s;
  512. {
  513.   /* find ewb <= s */
  514.   char  *s1 = s;
  515.   while(*--s1 != EOL) ;
  516.   while(ewb > s) cursor_up();
  517.   while(ewb < s1) cursor_down();
  518.   goto_x(s-ewb);
  519.   if(y > swh) y = flag[SHW] = swh/4;
  520. }
  521.  
  522. void goto_row()
  523. {
  524.   static char rbuf[6];
  525.   show_gets("Goto line", rbuf);
  526.   goto_y(atoi(rbuf)-1);
  527. }
  528.  
  529. void goto_col()
  530. {
  531.   static char cbuf[6];
  532.   show_gets("Goto Column", cbuf);
  533.   goto_x(atoi(cbuf) );
  534. }
  535.  
  536. /* compare to sbuf. used by search */
  537. int str_cmp(s)
  538. char *s;
  539. {
  540.   char  *d = sbuf;
  541.   if(flag[CAS] ) {
  542.     while(*d ) if(*s++ != *d++ ) return 1;
  543.     return 0;
  544.   }
  545.   while(*d ) if(tolower(*s++) != tolower(*d++)) return 1;
  546.   return 0;
  547. }
  548.  
  549. /* back / forward search */
  550. char *goto_find(s, back)
  551. char *s;
  552. int  back;
  553. {
  554.   do {
  555.     if(back ) {
  556.       if(--s <= aa) return 0;
  557.     }
  558.     else if(++s >= ae) return 0;
  559.   } while(str_cmp(s) );
  560.   goto_ptr(s);
  561.   return s;
  562. }
  563.  
  564. void goto_search(back)
  565. int  back;
  566. {
  567.   if(show_gets("Search for", sbuf) ) return;
  568.   goto_find(dp, back);
  569. }
  570.  
  571. void goto_replace(whole)
  572. int whole;
  573. {
  574.   char  *s=dp;
  575.   int rlen, slen = strlen(sbuf);
  576.   if(str_cmp(s) || str_cmp(rbuf) == 0 ||
  577.   show_gets("Replace with", rbuf) ) return;
  578.   rlen = strlen(rbuf);
  579.   do {
  580.     file_rs(s+slen, s+rlen);
  581.     memcpy(s, rbuf, rlen);
  582.   }
  583.   while(whole && (s=goto_find(s, 0)) != 0) ;
  584.   if(whole) flag[SHW]++;
  585.   else {
  586.     gotoxy(x, y+y2);
  587.     show_rest(sww-x, s);
  588.   }
  589. }
  590.  
  591. /* windows ---*/
  592. void window_other()
  593. {
  594.   int i;
  595.   wincopy = win;
  596.   win = winnext;
  597.   winnext = wincopy;
  598.   winnext.jump = ++ytru;
  599.   if(y1 > YTOP + 2) {
  600.     gotoxy(1, YTOP);
  601.     for(i=0; i<swhfull/2; i++) delline();
  602.   }
  603.   else {
  604.     y1 += swhfull/2;
  605.     swh -= swhfull/2;
  606.   }
  607. }
  608.  
  609. void window_cancel()
  610. {
  611.   if(y1 > YTOP+2) {
  612.     y1 -= swhfull/2;
  613.     y2 = y1 + 1;
  614.     swh += swhfull/2;
  615.     show_top();
  616.     flag[SHW]++;
  617.   }
  618. }
  619.  
  620. void window_size()
  621. {
  622.   static char wbuf[8]="68";
  623.   if(show_gets("Right margin",wbuf) == 0) {
  624.     sww = atoi(wbuf);
  625.     flag[SHW]++;
  626.   }
  627. }
  628.  
  629. /* block and format ---*/
  630. /* use blen, mk, bb */
  631. FILE *fb;
  632. void block_put()
  633. {
  634.   if(blen < BMAX) memcpy(bb, mk, blen);
  635.   else {
  636.     if(fb == 0 && (fb = tmpfile()) == 0) return;
  637.     fseek(fb, 0L, 0);
  638.     fwrite(mk, 1, blen, fb);
  639.   }
  640.   show_note("Block copied");
  641. }
  642.  
  643. void block_get()
  644. {
  645.   int i;
  646.   if(blen < BMAX) memcpy(mk, bb, blen);
  647.   else {
  648.     if(fb == 0) return;
  649.     fseek(fb, 0L, 0);
  650.     fread(mk, 1, blen, fb);
  651.   }
  652.   /* calculate ytot */
  653.   for(i=0; i<blen; i++) if(mk[i] == EOL) ytot++;
  654. }
  655.  
  656. void block_mark()
  657. {
  658.   if(*dp == EOL)
  659.     show_note("Invalid Pos.");
  660.   else {
  661.     show_note("Mark Set");
  662.     mk = dp;
  663.   }
  664. }
  665.  
  666. void block_copy(delete)
  667. int delete;
  668. {
  669.   blen = dp - mk;
  670.   block_put();
  671.   if(delete) {
  672.     goto_ptr(mk);
  673.     file_rs(dp, mk);
  674.     flag[SHW]++;
  675.   }
  676. }
  677.  
  678. void block_paste()
  679. {
  680.   mk = dp;
  681.   file_rs(mk, mk+blen);
  682.   block_get();    /* disk file ??? */
  683.   /* if it is a line */
  684.   if(xtru == 1 && strlen(mk) == blen-1) show_sdn(y);
  685.   else {
  686.     show_scr(y, swh);
  687.     goto_ptr(mk+blen);
  688.   }
  689. }
  690.  
  691. /* copy block to file, not to block buffer */
  692. void block_write()
  693. {
  694.   FILE  *fp;
  695.   static char fbuf[20] = "tmp.tmp";
  696.   if(mk >= dp) return;
  697.   if(show_gets("Write to file", fbuf) ) return;
  698.   fp = fopen(fbuf, "w");
  699.   file_write(fp, mk, dp);
  700. }
  701.  
  702. void block_line()
  703. {
  704.   if(ytru == ytot) return;
  705.   goto_x(1 );
  706.   for(blen = 0; ewb[++blen] != EOL; ) ;
  707.   mk = ewb+1;
  708.   block_put();
  709.   file_rs(ewb+blen, ewb);
  710.   show_sup(y);
  711. }
  712.  
  713. /* fill current line; does not change corsur or file len */
  714. int block_fill()
  715. {
  716.   int i=sww;
  717.   while(ewb[--i] > BLK) ;
  718.   if(i == 0) i = sww-1;
  719.   ewb[i] = EOL;
  720.   ytot++;
  721.   cursor_down();
  722.   return i;
  723.   /* screen position to clreol() */
  724. }
  725.  
  726. /* format paragraph */
  727. void block_format()
  728. {
  729.   char  *s=ewb;
  730.   int ytmp = y;
  731.   goto_x(1);
  732.   while(s = strchr(++s, EOL), ytru < ytot && s[1] != EOL) {
  733.     s[0] = BLK;
  734.     ytot--;
  735.   }
  736.   while(strlen(ewb+1) >= sww) block_fill();
  737.   while(ewb[xtru] ) cursor_right();
  738.   if( flag[SHW] == 0) show_scr(ytmp, swh);
  739. }
  740.  
  741. /* key actions ---*/
  742. /* update file part, then screen ... */
  743. void key_return()
  744. {
  745.   char  *s=dp;
  746.   if(flag[OVR] ) {
  747.     cursor_down();
  748.     goto_x(1);
  749.     return;
  750.   }
  751.   file_rs(s, s+1);
  752.   goto_x(1);
  753.   *s = EOL;
  754.   ytot++;
  755.   cursor_down();
  756.   if(flag[SHW] == 0) {
  757.     clreol();
  758.     if(y < sww) show_sdn(y);
  759.   }
  760. }
  761.  
  762. /* used by next two */
  763. void key_deleol(s)
  764. char *s;
  765. {
  766.   if(ytru == ytot) return;
  767.   goto_x(s-ewb);
  768.   file_rs(s+1, s);
  769.   if(flag[SHW] ) return;
  770.   if(y < 0) {   /* y = -1 */
  771.     y = 0;
  772.     show_scr(0,0);
  773.   }
  774.   else {
  775.     gotoxy(x, y+y2);
  776.     show_rest(sww-x, s);
  777.     show_sup(y+1);
  778.   }
  779. }
  780.  
  781. /* delete under */
  782. void key_delete()
  783. {
  784.   char  *s=dp;
  785.   if( *s == EOL) {
  786.     key_deleol(s);
  787.     return;
  788.   }
  789.   file_rs(s+1, s);
  790.   show_rest(sww-x, s);
  791. }
  792.  
  793. void key_backspace()
  794. {
  795.   char  *s=dp;
  796.   if(*--s == EOL) { /* delete EOL */
  797.     if(ytru == 0) return;
  798.     cursor_up();
  799.     key_deleol(s);
  800.     return;
  801.   }
  802.   while(ewb+xtru > s) cursor_left();
  803.   /* delete tab space */
  804.   if(*s == BLK) {
  805.     while(*--s == BLK && (xtru%tabsize) != 1) cursor_left();
  806.     s++;
  807.   }
  808.   file_rs(dp, s);
  809.   if(!flag[SHW] ) {
  810.     gotoxy(x, y+y2);
  811.     show_rest(sww-x, s);
  812.   }
  813. }
  814.  
  815. void key_delword(eol)
  816. int  eol;
  817. {
  818.   char  *d=dp;
  819.   if(*d == EOL) {
  820.     key_deleol(d);
  821.     return;
  822.   }
  823.   if(eol) while(*d != EOL) d++;
  824.   else {
  825.     while(*d > BLK) d++;
  826.     while(*d == BLK) d++;
  827.   }
  828.   show_rest(sww-x, d);
  829.   file_rs(d, dp);
  830. }
  831.  
  832. void key_tab(tabi)
  833. int tabi;
  834. {
  835.   char  *s = ewb+xtru;
  836.   int xtmp=x;
  837.   do cursor_right();
  838.   while((xtru%tabsize) != 1);
  839.   if(!tabi && s==dp) {
  840.     s = ewb+xtru;
  841.     file_rs(dp, s); /* may change cursor_position */
  842.     while(s > dp) *--s = BLK;
  843.     gotoxy(xtmp, y+y2);
  844.     show_rest(sww-xtmp, s);
  845.   }
  846. }
  847.  
  848. void key_normal(key)
  849. int key;
  850. {
  851.   char  *s=ewb+xtru;
  852.   int xtmp;
  853.   if(dp < s) {
  854.     file_rs(dp, s);
  855.     while(dp < s) *dp++ = BLK;
  856.   }
  857.   if(flag[OVR] && *s != EOL) {
  858.     putch(*s = key);
  859.     flag[CHG] = 1;
  860.   }
  861.   else {
  862.     file_rs(s, ++dp);
  863.     *s = key;
  864.     show_rest(sww-x, s);
  865.   }
  866.   cursor_right();
  867.   if(!flag[FIL] || xtru<sww) return;
  868.  
  869.   xtmp = block_fill();  /* cursor_down */
  870.   if(xtru > sww) flag[SHW]++;
  871.   xtru = x = xtru - xtmp;
  872.   if(flag[SHW] == 0) {
  873.     gotoxy(xtmp, y2+y-1);
  874.     clreol();
  875.     show_sdn(y);
  876.   }
  877. }
  878.  
  879. void key_shell(line)  /* shell: `sh' on Unix, RET on MS-DOS or VMS */
  880. int line;
  881. {
  882.   static char mbuf[40];
  883.   if(line ) strcpy(mbuf, ewb+1);
  884.   else if(show_gets("Cmd", mbuf) ) return;
  885.   clrscr();
  886.   ttclose();
  887.   system(mbuf);
  888.   ttopen();
  889.   get_key();
  890.   show_top();
  891.   flag[SHW]++;
  892. }
  893.  
  894. void key_macros(record)
  895. int record;
  896. {
  897.   static char mbuf[60];
  898.   char  *s=mbuf;
  899.   void  main_exec();
  900.   int k;
  901.   if(!record) {
  902.     while(*s != 0) main_exec(*s++);
  903.     return;
  904.   }
  905.   show_note("^Z to end: ");
  906.   while( (k = get_key()) != 'Z'-'@') {
  907.     *s++ = k;
  908.     if(k < BLK) {
  909.       putch('^');
  910.       k |= 0x40;
  911.     }
  912.     putch(k);
  913.   }
  914.   *s = 0;
  915.   s = mbuf;
  916. }
  917.  
  918. /* main function */
  919. void main_meta(key)
  920. int key;
  921. {
  922.   switch(key | 0x60) {
  923.   case 'a': file_more(); break;
  924.   case 'b': window_size(); break;
  925.   case 'c': key_shell(1); break;
  926.   case 'd': goto_x(strlen(ewb+1)+1); break;
  927.   case 'e': goto_y(0); break;
  928.   case 'f': goto_search(1); break;
  929.   case 'g': goto_col(); break;
  930.   case 'h': key_delete(); break;
  931.   case 'i': key_tab(0); break;
  932.   case 'j': key_macros(1); break;
  933.   case 'k': block_copy(1); break;
  934.   case 'l': show_status(); break;
  935.   case 'm':
  936.   case 'n':
  937.   case 'o':
  938.   case 'p': key_normal(get_key() ); break;
  939.   case 'q': break;
  940.   case 'r': goto_replace(1); break;
  941.   case 's': goto_x(1); break;
  942.   case 't': key_delword(1); break;
  943.   case 'u': block_write(); break;
  944.   case 'v': cursor_pageup(); break;
  945.   case 'w': window_cancel(); break;
  946.   case 'x': goto_y(ytot); break;
  947.   case 'y': break;
  948.   case 'z': file_save(0, -1); break;
  949.   }
  950.   show_flag(ALT, 0);
  951. }
  952.  
  953. void main_exec(key)
  954. int key;
  955. {
  956.   int i = xtru;
  957.   dp = ewb;
  958.   while(*++dp && --i>0) ;
  959.   if(flag[ALT] ) main_meta(key);
  960.   else if(key >= BLK) key_normal(key);
  961.   else switch(key|0x60) {
  962.   case 'a': block_mark(); break;
  963.   case 'b': block_format(); break;
  964.   case 'c': key_shell(0); break;
  965.   case 'd': cursor_right(); break;
  966.   case 'e': cursor_up(); break;
  967.   case 'f': goto_search(0); break;
  968.   case 'g': goto_row(); break;
  969.   case 'h': key_backspace(); break;
  970.   case 'i': key_tab(1); break;
  971.   case 'j': key_macros(0); break;
  972.   case 'k': block_copy(0); break;
  973.   case 'l': if(ytru > swh/4) { y = swh/4; flag[SHW]++; } break;
  974.   case 'm': key_return(); break;
  975.   case 'n': show_flag(OVR, !flag[OVR]); break;
  976.   case 'o': show_mode(); break;
  977.   case 'p':
  978.   case 'q': show_flag(ALT, 1); break;
  979.   case 'r': goto_replace(0); break;
  980.   case 's': cursor_left(); break;
  981.   case 't': key_delword(0); break;
  982.   case 'u': block_paste(); break;
  983.   case 'v': cursor_pagedown(); break;
  984.   case 'w': file_save(0, 1); break;
  985.   case 'x': cursor_down(); break;
  986.   case 'y': block_line(); break;
  987.   case 'z':
  988.   case '{': file_save(1, 0); break;
  989.   case HLP|0x60: show_help();   /* | */
  990.   }
  991. }
  992.  
  993. /* win is only thing it knows */
  994. void main_loop()
  995. {
  996.   int  yold, xold;
  997.  
  998.   show_top();
  999.   if((fi = fopen(win.name, "r")) == 0) {
  1000.     show_note("New file");
  1001.     flag[NEW]++;
  1002.   }
  1003.   file_read();
  1004.  
  1005.   while(flag[EDT] == 0) {
  1006.     if(y <= -1 || y >= swh) {      /* change here if no hardware scroll */
  1007.       if(y == -1) {
  1008.         y++; show_sdn(0);
  1009.       }
  1010.       else if(y == swh) {
  1011.         y--; show_sup(0);
  1012.       }
  1013.       else {
  1014.         y = y < 0? 0: swh-1;
  1015.         show_scr(0, swh);
  1016.         flag[SHW] = 0;
  1017.       }
  1018.     }
  1019.     else if(flag[SHW] ) {
  1020.       show_scr(0, swh);
  1021.       flag[SHW] = 0;
  1022.     }
  1023.     if(flag[NTS] ) {
  1024.       show_note(flag[POS]? "Line      Col": "F1-Help");
  1025.       yold = xold = (-1);
  1026.       flag[NTS] = 0;
  1027.     }
  1028.     if(flag[POS] ) {
  1029.       if(ytru != yold) {
  1030.         yold = ytru;
  1031.         gotoxy(22+ALT, y1);
  1032.         cprintf("%-4d", ytru+1);
  1033.       }
  1034.       if(xtru != xold) {
  1035.         xold = xtru;
  1036.         gotoxy(31+ALT, y1);
  1037.         cprintf("%-3d", xtru);
  1038.       }
  1039.     }
  1040.     gotoxy(x, y+y2);
  1041.     main_exec(get_key() );
  1042.   }
  1043.   /* fo = 0; */
  1044. }
  1045.  
  1046. void main(argc, argv)
  1047. int  argc;
  1048. char **argv;
  1049. {
  1050.   /* set command line */
  1051.   while(--argc && **++argv == '-') switch(*++*argv) {
  1052.     case 't': tabsize = atoi(++*argv); break;
  1053.     case '+': win.jump = atoi(++*argv); break;
  1054.   }
  1055.   strcpy(win.name, argc == 0? "Notes": *argv);
  1056.   aa[0] = EOL;
  1057.  
  1058.   ttopen();
  1059.   swh = swhfull;
  1060.   y1 = YTOP;
  1061.  
  1062.   do {
  1063.     y2 = y1+1;
  1064.     flag[SHW]++;
  1065.     flag[NEW] = flag[EDT] = flag[ALL] = 0;
  1066.     main_loop();
  1067.     if(flag[WIN] > 0) window_other(win);
  1068.     if(flag[WIN] < 0 || *win.name == 0)
  1069.       show_gets("File name", win.name);
  1070.     flag[WIN] = 0;
  1071.   } while(flag[ALL] == 0) ;
  1072.  
  1073.   gotoxy(1, swhfull+2);
  1074.   ttclose();
  1075. }
  1076.  
  1077.